﻿using System;
using System.Linq;
using System.Web;
using EPiServer;
using EPiServer.Core;
using EPiServer.Core.Html;
using EPiServer.DataAbstraction;
using EPiServer.DataAccess;
using EPiServer.Framework;
using EPiServer.Security;
using TemplateFoundation.Configuration;
using TemplateFoundation.PageTypes;

namespace TemplateFoundation.EventHandlers
{
    /// <summary>
    /// Used to set calculated default values that cannot be configured as page property default values
    /// </summary>
    /// <remarks>Examples include setting the Title property to the name of the page which cannot be done until the page is saved</remarks>
    [InitializableModule]
    [ModuleDependency(typeof(PageTypeBuilder.Initializer))]
    public class DefaultPropertyValues : IInitializableModule
    {
        private bool _creatingPageEventAttached;

        void SetDefaultPropertyValues(object sender, PageEventArgs e)
        {
            // We need a version list in case we have to compare property values with previous page versions
            var versions = DataFactory.Instance.ListVersions(e.PageLink, e.Page.LanguageBranch);

            var page = e.Page as PageTypeBase;

            if(page==null)
            {
                // No action performed if the page isn't a valid PageTypeBase object
                return;
            }

            // Set page title property if it hasn't been set
            if(string.IsNullOrEmpty(page.Title))
            {
                page.Title = page.PageName;
            }

            // If the page title had its default value based on the page name, and the page name changed - we should update the title as well
            if (versions.Any())
            {
                // Get previous page name
                var previousPageName = DataFactory.Instance.GetPage(versions[0].ID).PageName;

                // Check if page name has been changed
                if (e.Page.PageName!=previousPageName)
                {
                    var previousTitle = ((PageTypeBase) e.Page).Title;
                 
                    // Check if previous title was the same as the page name
                    if(previousTitle==previousPageName)
                    {
                        // Update title to the new page name
                        page.Title = page.PageName;
                    }
                }
            }

            // Use tags for keywords if no keywords have been specified)
            if(string.IsNullOrEmpty(page.Keywords))
            {
                if (page.Tags!=null)
                {
                    page.Keywords = string.Join(",", page.Tags.ToStringArray());
                }
            }

            // If the page description had its default value based on the main body, and the main body content changed - we should update the description as well
            if (page is StandardPageBase)
            {
                if (!versions.Any())
                {
                    if (string.IsNullOrEmpty(page.Description)) // No description set, and it cannot have been explicitly deleted by an editor in a previous version
                    {
                        page.Description = HttpUtility.HtmlDecode(TextIndexer.StripHtml(((StandardPageBase)page).MainBody, 160, 20, "...").Trim());    
                    }
                }
                else // Previous versions exist, but we'll update the description if it hasn't been explicitly modified by the editor
                {
                    if (page.Description==HttpUtility.HtmlDecode(TextIndexer.StripHtml(((StandardPageBase)DataFactory.Instance.GetPage(versions[0].ID)).MainBody, 160, 20, "...").Trim()))
                    {
                        // Previous description was set by ETF (to an excerpt of the main body content) so we will update the description
                        page.Description = HttpUtility.HtmlDecode(TextIndexer.StripHtml(((StandardPageBase)page).MainBody, 160, 20, "...").Trim());    
                    }
                    else
                    {
                        // We'll leave the explicitly set description, but we'll replace an empty string with null
                        if (page.Description != null && string.IsNullOrEmpty(page.Description.Trim()))
                        {
                            page.Description = null;
                        }
                    }
                }               
            }

            // Article date and tag listings shouldn't be visible in menus by default (only set when page is first created)
            if (!DataFactory.Instance.ListVersions(page.PageLink).Any())
            {
                if (page is ArticleDateListingPageBase || page is ArticleTagListingPageBase)
                {
                    if (page.IsMasterLanguageBranch) // 'Visible in menus' can only be set using the master language
                    {
                        page.VisibleInMenu = false;
                    }
                    else // Edit the master language version
                    {
                        var p = page.GetPageLanguage(page.MasterLanguageBranch).CreateWritableClone();
                        p.VisibleInMenu = false;
                        DataFactory.Instance.Save(p, SaveAction.ForceCurrentVersion, AccessLevel.Read);
                    }
                }
            }
        }

        #region IInitializableModule Members

        /// <summary>
        /// Initializes the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Initialize(EPiServer.Framework.Initialization.InitializationEngine context)
        {
            if (!_creatingPageEventAttached)
            {
                DataFactory.Instance.SavingPage+=SetDefaultPropertyValues;
                DataFactory.Instance.PublishingPage+=SetDefaultPropertyValues;
            }

            _creatingPageEventAttached = true;
        }

        /// <summary>
        /// Not implemented
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        public void Preload(string[] parameters) { throw new NotImplementedException(); }

        /// <summary>
        /// Not implemented
        /// </summary>
        /// <param name="context">The context.</param>
        public void Uninitialize(EPiServer.Framework.Initialization.InitializationEngine context) { }

        #endregion
    }
}
